Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add AmazonS3Resolver and ResolverInterface::remove #66

Merged
merged 2 commits into from
May 4, 2012

Conversation

havvg
Copy link
Contributor

@havvg havvg commented Apr 23, 2012

In addition there is a re-factoring considering the browser path.
I stumbled upon this, while creating the resolver. The browser path of this resolver is an external URL. Therefore the getBrowserPath has been moved into the ResolverInterface.

havvg added 2 commits April 23, 2012 18:37
* move getBrowserPath() from CacheManager into ResolverInterface
@lsmith77
Copy link
Contributor

lsmith77 commented May 2, 2012

ok looks sensible after a first quick skim. need to analyze the refactoring some more. will get to it some time this week.

/**
* {@inheritDoc}
*/
public function remove($targetPath, $filter)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't this method be moved to AbstractFilesystemResolver ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it can; will update it.

lsmith77 added a commit that referenced this pull request May 4, 2012
add AmazonS3Resolver and ResolverInterface::remove
@lsmith77 lsmith77 merged commit 18875c1 into liip:master May 4, 2012
@lsmith77
Copy link
Contributor

lsmith77 commented May 4, 2012

ok .. i have merged the current state .. see my comment about the remove method though.

@havvg
Copy link
Contributor Author

havvg commented May 4, 2012

Oh, then I was to late; if this one is fine I'll open another PR: havvg/LiipImagineBundle@46450984

@lsmith77
Copy link
Contributor

lsmith77 commented May 4, 2012

yeah .. looks good.

@Spea
Copy link

Spea commented May 5, 2012

Nice implementation. I just tested it and all worked fine, but my site slowed down a bit. After some debugging, I found out that the method if_object_exists takes approx. 0.3 seconds.

Here is the code I used to test this behavior

<?php
require_once __DIR__.'/../vendor/aws-sdk/sdk.class.php';
define("AWS_CERTIFICATE_AUTHORITY", true);

$s3 = new AmazonS3(array('key' => '...', 'secret' => '....'));

$start = microtime(true);
$s3->if_object_exists('my-bucket', 'filename.txt');
$end = microtime(true);

var_dump($end - $start);

As you can imagine, this is not a practical solution for a production environment. I still couldn't find another way to check if the image/object already exists. Maybe it should be cached somewhere (database?) that the object exists when the thumb is created.

Any suggestion?

@lsmith77
Copy link
Contributor

lsmith77 commented May 5, 2012

yeah .. the iffy bit is that there is no goto caching bundle for Symfony2 yet ..

@Spea
Copy link

Spea commented May 5, 2012

Yeah right. What do you think about implementing a caching layer in this bundle or just an interface which could be used to implement caching for the resolvers?

@lsmith77
Copy link
Contributor

lsmith77 commented May 5, 2012

seems like choosing a poison :-/

there is LiipDoctrineCacheBundle .. which however could use some love to make it easier to configure stuff like memcache(d).

@neilferreira
Copy link

Hi,

I've just started to use this, and @Spea is correct, is is a bit slow. I'm surprised there is no go-to caching bundle, surely knocking one up wouldn't even be too difficult (could use the doctrine one as an example) - for now as a quickfix and we just use APC? I can't imagine too many sites running with APC disabled (wrap a check around whether or not apc is enabled ofcourse).

Cheers.

@neilferreira
Copy link

I've also just noticed another problem that I'm hoping @havvg may get around to looking into.

I am using the SteamLoader you've recently introduced and this s3 resolver and I've run into a bit of a problem, probably partly due to the way I've set it up, but I think someone else it bound to run into the same issue,

My gaufrette config:

knp_gaufrette:
    adapters:
        media_cache:
            local:
                directory: %kernel.root_dir%/../web/media/cache/
gaufrette.filesystem.media_cache:
        class: Gaufrette\Filesystem
        factory_service: 'knp_gaufrette.filesystem_map'
        factory_method: 'get'
        arguments:
            - 'media_cache'
        tags:
            - { name: 'my_site.stream_filesystem', alias: 'media_cache' }

I'm using one single 'media cache' filesystem, and writing multiple cached copies of images into subdirectories, ie:

$filesystem = $this->getContainer()->get('gaufrette.filesystem.media_cache');
$cacheKey = '/composite/' . $entry->getId()) . '.jpg';
$filesystem->write($cacheKey, $imageData);

This now writes out my images to /web/media/cache/composite/ (I can post up more of my config if you're confused)

Now when I use the amazon loader, it attempts to determine if the file is already on s3 inside the getBrowserPath function

In this section:

$objectPath = $this->getObjectPath($targetPath, $filter);
if ($this->storage->if_object_exists($this->bucket, $objectPath)) {

Unfortunately getObjectPath inserts another / into the middle of the $filter and $path

protected function getObjectPath($path, $filter)
    {
        return $filter.'/'.$path;
    }

Which returns:
[imaginefiltername]//composite/819237ea4e16337558cc9cb6ecf4be06.jpg

When the call if "if object exists" is made, it always return false because of the double slash, then tries writing the file to s3 on every request. The getObjectPath function should check the first char of $path for a /.

Cheers.

@neilferreira
Copy link

One last one, I promise

When you make the call to $this->storage->get_object_url($this->bucket, $objectPath) there is one problem.

If the user is browsing the site via SSL, you'll be supplying them a URL to an image not served via SSL, although s3 does support ssl.

One thing I was thinking is just stripping off 'http:' from the URL and serving '//bucket.amazon' (similar to how jquery is served here: //ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js) that way you don't have to check if the current request is being served via HTTPs)

What I did just notice though is that my content is being served via:
http://[mybucket].s3.amazonaws.com/compositeWelcomeBack/composite/819237ea4e16337558cc9cb6ecf4be06.jpg

Weirdly adding https:// to this url, this throws up a bug SSL warning, there is a certficate for '*.s3.amazonaws.com' but my browser doesn't appear to like it, at all (Chrome + FF)

If you try:
$this->storage->get_object_url($this->bucket, $objectPath, 0, array('https' => true));

You'll notice that is returns the exact same URL, with https:// prepended to it, the url amazon generates via AWS console is:
https://s3-ap-southeast-1.amazonaws.com/[mybucket]/compositeWelcomeBack/composite/819237ea4e16337558cc9cb6ecf4be06.jpg

Can anyone comment on whether or not that SSL cert should have validated in the first place? Or an alternative solution to this issue?

p.s: @lsmith77 can we re-open this issue, it feels weird going on inside a closed issue.

@neilferreira
Copy link

I just remembered there is a note about SSL and Amazon, not sure if related, see: "Amazon S3" on https://github.com/KnpLabs/Gaufrette

@havvg
Copy link
Contributor Author

havvg commented May 7, 2012

Thank you for all the feedback! I'll open up a hotfix branch for this and apply the feedback to it.

@advancingu
Copy link

Has anyone gotten around to looking into caching to mitigate the slowdown caused by if_object_exists() calls?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants